
interface Event {
  func: Function
  ctx: unknown
}

export class EventManager{

  private static instance: EventManager;
  private eventMap: Map<string, Event[]>;


  static getInstance(): EventManager{
    if(!this.instance){
      this.instance = new EventManager()
      this.instance.eventMap = new Map()
    }
    return this.instance
  }


  on(eventName:string, func: Function, ctx?: unknown){
    const eventList = this.eventMap.get(eventName)
    if (eventList){
      eventList.push({func, ctx})
    } else {
      this.eventMap.set(eventName, [{func, ctx}])
    }
  }

  off(eventName:string, func: Function) {
    const eventList = this.eventMap.get(eventName) || []
    const index = eventList.findIndex(item => item.func === func)
    index > -1 && eventList.splice(index, 1)
  }

  emit(eventName: string, ...args: any[]){
    this.eventMap.get(eventName)?.forEach(event => {
      const {func, ctx} = event
      ctx ? func.apply(ctx, args) : func(...args)
    })
  }

  clear(){
    this.eventMap.clear()
  }


}
